/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package team11;

import java.util.Random;

/**
 * 数据生成和归一化工具类 提供训练数据生成、目标值计算和归一化功能
 *
 * @author 朱婧雯
 */
public class Data {

    public static double minTarget = Double.POSITIVE_INFINITY;
    public static double maxTarget = Double.NEGATIVE_INFINITY;

    /**
     * 生成指定数量的训练数据样本
     *
     * @param samples
     * @param min
     * @param max
     * @param func
     * @return
     */
    public static double[][] generateData(int samples, double min, double max, Func func) {
        Random rand = new Random(42);
        double[][] data = new double[samples][2];

        minTarget = Double.POSITIVE_INFINITY;
        maxTarget = Double.NEGATIVE_INFINITY;

        for (int i = 0; i < samples; i++) {
            double x = min + (max - min) * rand.nextDouble();
            double y = min + (max - min) * rand.nextDouble();
            data[i][0] = x;
            data[i][1] = y;

            double z = func.getValue(x, y);

            if (z < minTarget) {
                minTarget = z;
            }
            if (z > maxTarget) {
                maxTarget = z;
            }
        }

        return data;
    }

    /**
     * 批量生成目标值
     *
     * @param inputs
     * @param func
     * @return
     */
    public static double[][] generateTargets(double[][] inputs, Func func) {
        double[][] targets = new double[inputs.length][1];

        for (int i = 0; i < inputs.length; i++) {
            targets[i][0] = func.getValue(inputs[i][0], inputs[i][1]);
        }

        return targets;
    }

    /**
     * 增强的归一化方法，支持自定义范围
     *
     * @param targets
     * @param outputMin
     * @param outputMax
     */
    public static void normalizeTargets(double[][] targets, double outputMin, double outputMax) {
        validateNormalizationParams();

        double range = maxTarget - minTarget;
        if (Math.abs(range) < 1e-10) {
            // 如果所有目标值相同，设置为中间值
            double mid = (outputMin + outputMax) / 2;
            for (double[] target : targets) {
                target[0] = mid;
            }
            return;
        }

        double outputRange = outputMax - outputMin;
        for (double[] target : targets) {
            target[0] = outputMin + outputRange * ((target[0] - minTarget) / range);
        }
    }

    /**
     * 默认归一化到[0.1, 0.9]范围
     *
     * @param targets
     */
    public static void normalizeTargets(double[][] targets) {
        normalizeTargets(targets, 0.1, 0.9);
    }

    /**
     * 参数验证方法
     */
    private static void validateNormalizationParams() {
        if (Double.isInfinite(minTarget) || Double.isInfinite(maxTarget)) {
            throw new IllegalStateException("请先调用generateData方法初始化归一化参数");
        }
        if (Double.isNaN(minTarget) || Double.isNaN(maxTarget)) {
            throw new IllegalStateException("归一化参数包含NaN值");
        }
    }

    /**
     * 增强的反归一化方法
     *
     * @param normalized
     * @param outputMin
     * @param outputMax
     * @return
     */
    public static double denormalize(double normalized, double outputMin, double outputMax) {
        validateNormalizationParams();

        double range = maxTarget - minTarget;
        double outputRange = outputMax - outputMin;

        return minTarget + (normalized - outputMin) * range / outputRange;
    }

    /**
     * 默认反归一化（从[0.1, 0.9]范围）
     *
     * @param normalized
     * @return
     */
    public static double denormalize(double normalized) {
        return denormalize(normalized, 0.1, 0.9);
    }

    /**
     * 获取归一化参数信息
     *
     * @return
     */
    public static String getNormalizationInfo() {
        return String.format("归一化范围: [%.6f, %.6f] -> [0.1, 0.9]", minTarget, maxTarget);
    }
}
